﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace LogExpert
{
	public partial class PatternWindow : Form
	{
		List<List<PatternBlock>> blockList = new List<List<PatternBlock>>();
		List<PatternBlock> currentList;
		PatternBlock currentBlock;
		PatternArgs patternArgs = new PatternArgs();

		LogWindow logWindow;
  
		public int Fuzzy
		{
			set
			{
				this.fuzzyKnobControl.Value = value;
			}
			get
			{
				return this.fuzzyKnobControl.Value;
			}
		}

		public int MaxDiff
		{
			set
			{
				this.maxDiffKnobControl.Value = value;
			}
			get
			{
				return this.maxDiffKnobControl.Value;
			}
		}

		public int MaxMisses
		{
			set
			{
				this.maxMissesKnobControl.Value = value;
			}
			get
			{
				return this.maxMissesKnobControl.Value;
			}
		}

		public int Weight
		{
			set
			{
				this.weigthKnobControl.Value = value;
			}
			get
			{
				return this.weigthKnobControl.Value;
			}
		}

		public PatternWindow()
		{
			InitializeComponent();
		}

		public PatternWindow(LogWindow logWindow)
		{
			this.logWindow = logWindow;
			InitializeComponent();
			this.recalcButton.Enabled = false;
		}

		public void SetBlockList(List<PatternBlock> flatBlockList, PatternArgs patternArgs)
		{
			this.patternArgs = patternArgs;
			blockList.Clear();
			List<PatternBlock> singeList = new List<PatternBlock>();
			//int blockId = -1;
			for (int i = 0; i < flatBlockList.Count; ++i)
			{
				PatternBlock block = flatBlockList[i];
				singeList.Add(block);
				//if (block.blockId != blockId)
				//{
				//  singeList = new List<PatternBlock>();
				//  PatternBlock selfRefBlock = new PatternBlock();
				//  selfRefBlock.targetStart = block.startLine;
				//  selfRefBlock.targetEnd = block.endLine;
				//  selfRefBlock.blockId = block.blockId;
				//  singeList.Add(selfRefBlock);
				//  singeList.Add(block);
				//  this.blockList.Add(singeList);
				//  blockId = block.blockId;
				//}
				//else
				//{
				//  singeList.Add(block);
				//}
			}
			this.blockList.Add(singeList);
			this.Invoke(new MethodInvoker(SetBlockListGuiStuff));
		}

		private void SetBlockListGuiStuff()
		{
			this.patternHitsDataGridView.RowCount = 0;
			this.blockCountLabel.Text = "0";
			this.contentDataGridView.RowCount = 0;
			this.blockLinesLabel.Text = "0";
			this.recalcButton.Enabled = true;
			this.setRangeButton.Enabled = true;
			if (this.blockList.Count > 0)
			{
				SetCurrentList(this.blockList[0]);
			}
		}

		private void SetCurrentList(List<PatternBlock> patternList)
		{
			this.patternHitsDataGridView.RowCount = 0;
			this.currentList = patternList;
			this.patternHitsDataGridView.RowCount = this.currentList.Count;
			this.patternHitsDataGridView.Refresh();
			this.blockCountLabel.Text = "" + this.currentList.Count;
		}

		public void SetColumnizer(ILogLineColumnizer columnizer)
		{
			this.logWindow.SetColumnizer(columnizer, this.patternHitsDataGridView);
			this.logWindow.SetColumnizer(columnizer, this.contentDataGridView);
			this.patternHitsDataGridView.Columns[0].Width = 20;
			this.contentDataGridView.Columns[0].Width = 20;

			DataGridViewTextBoxColumn blockInfoColumn = new DataGridViewTextBoxColumn();
			blockInfoColumn.HeaderText = "Weight";
			blockInfoColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet;
			blockInfoColumn.Resizable = DataGridViewTriState.False;
			blockInfoColumn.DividerWidth = 1;
			blockInfoColumn.ReadOnly = true;
			blockInfoColumn.Width = 50;

			DataGridViewTextBoxColumn contentInfoColumn = new DataGridViewTextBoxColumn();
			contentInfoColumn.HeaderText = "Diff";
			contentInfoColumn.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet;
			contentInfoColumn.Resizable = DataGridViewTriState.False;
			contentInfoColumn.DividerWidth = 1;
			contentInfoColumn.ReadOnly = true;
			contentInfoColumn.Width = 50;

			this.patternHitsDataGridView.Columns.Insert(1, blockInfoColumn);
			this.contentDataGridView.Columns.Insert(1, contentInfoColumn);
		}

		public void SetFont(string fontName, float fontSize)
		{
			Font font = new Font(new FontFamily(fontName), fontSize);
			int lineSpacing = font.FontFamily.GetLineSpacing(FontStyle.Regular);
			float lineSpacingPixel = font.Size * lineSpacing / font.FontFamily.GetEmHeight(FontStyle.Regular);

			this.patternHitsDataGridView.DefaultCellStyle.Font = font;
			this.contentDataGridView.DefaultCellStyle.Font = font;
			//this.lineHeight = font.Height + 4;
			this.patternHitsDataGridView.RowTemplate.Height = font.Height + 4;
			this.contentDataGridView.RowTemplate.Height = font.Height + 4;
		}

		private void patternHitsDataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
		{
			if (this.currentList == null || e.RowIndex < 0)
				return;
			int rowIndex = GetLineForHitGrid(e.RowIndex);
			int colIndex = e.ColumnIndex;
			if (colIndex == 1)
			{
				e.Value = currentList[e.RowIndex].Weigth;
			}
			else
			{
				if (colIndex > 1)
				{
					colIndex--;  // correct the additional inserted col
				}
				e.Value = this.logWindow.GetCellValue(rowIndex, colIndex);
			}
		}

		private void patternHitsDataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
		{
			if (this.currentList == null || e.RowIndex < 0)
				return;
			if (e.ColumnIndex == 1)
			{
				e.PaintBackground(e.CellBounds, false);
				int selCount = (this.patternArgs.endLine - this.patternArgs.startLine);
				int maxWeight = this.patternArgs.maxDiffInBlock * selCount + selCount;
				if (maxWeight > 0)
				{
					int width = (int)(((double)(int)e.Value / (double)maxWeight) * (double)e.CellBounds.Width);
					Rectangle rect = new Rectangle(e.CellBounds.X, e.CellBounds.Y, width, e.CellBounds.Height);
					int alpha = 90 + (int)(((double)(int)e.Value / (double)maxWeight) * (double)165);
					Color color = Color.FromArgb(alpha, 170, 180, 150);
					Brush brush = new SolidBrush(color);
					rect.Inflate(-2, -1);
					e.Graphics.FillRectangle(brush, rect);
					brush.Dispose();
				}
				e.PaintContent(e.CellBounds);
				e.Handled = true;
			}
			else
			{
				DataGridView gridView = (DataGridView)sender;
				int rowIndex = GetLineForHitGrid(e.RowIndex);
				PaintHelper.CellPainting(logWindow,gridView, rowIndex, e); //TODO Zarunbal: check if it works!
			}
		}

		private void patternHitsDataGridView_MouseDoubleClick(object sender, MouseEventArgs e)
		{
			//if (this.currentList == null || patternHitsDataGridView.CurrentRow == null)
			//  return;
			//int rowIndex = GetLineForHitGrid(patternHitsDataGridView.CurrentRow.Index);
			//this.logWindow.SelectLogLine(rowIndex);
		}

		private int GetLineForHitGrid(int rowIndex)
		{
			int line;
			line = currentList[rowIndex].TargetStart;
			return line;
		}

		private int GetLineForContentGrid(int rowIndex)
		{
			int line;
			line = currentBlock.TargetStart + rowIndex;
			return line;
		}

		private void patternHitsDataGridView_CurrentCellChanged(object sender, EventArgs e)
		{
			if (this.currentList == null || patternHitsDataGridView.CurrentRow == null)
				return;
			if (patternHitsDataGridView.CurrentRow.Index > this.currentList.Count - 1)
				return;
			this.contentDataGridView.RowCount = 0;
			this.currentBlock = this.currentList[patternHitsDataGridView.CurrentRow.Index];
			this.contentDataGridView.RowCount = this.currentBlock.TargetEnd - this.currentBlock.TargetStart + 1;
			this.contentDataGridView.Refresh();
			this.contentDataGridView.CurrentCell = this.contentDataGridView.Rows[0].Cells[0];
			this.blockLinesLabel.Text = "" + this.contentDataGridView.RowCount;
		}

		private void contentDataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
		{
			if (this.currentBlock == null || e.RowIndex < 0)
				return;
			int rowIndex = GetLineForContentGrid(e.RowIndex);
			int colIndex = e.ColumnIndex;
			if (colIndex == 1)
			{
				QualityInfo qi;
				if (this.currentBlock.QualityInfoList.TryGetValue(rowIndex, out qi))
				{
					e.Value = qi.Quality;
				}
				else
				{
					e.Value = "";
				}
			}
			else
			{
				if (colIndex != 0)
				{
					colIndex--; // adjust the inserted column
				}
				e.Value = this.logWindow.GetCellValue(rowIndex, colIndex);
			}
		}

		private void contentDataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
		{
			if (this.currentBlock == null || e.RowIndex < 0)
				return;
			DataGridView gridView = (DataGridView)sender;
			int rowIndex = GetLineForContentGrid(e.RowIndex);
			PaintHelper.CellPainting(logWindow, gridView, rowIndex, e);
		}

		private void contentDataGridView_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
		{
			if (this.currentBlock == null || contentDataGridView.CurrentRow == null)
			{
				return;
			}
			int rowIndex = GetLineForContentGrid(contentDataGridView.CurrentRow.Index);

			logWindow.SelectLogLine(rowIndex);
		}

		private void recalcButton_Click(object sender, EventArgs e)
		{
			patternArgs.fuzzy = this.fuzzyKnobControl.Value;
			patternArgs.maxDiffInBlock = this.maxDiffKnobControl.Value;
			patternArgs.maxMisses = this.maxMissesKnobControl.Value;
			patternArgs.minWeight = this.weigthKnobControl.Value;
			this.logWindow.PatternStatistic(patternArgs);
			this.recalcButton.Enabled = false;
			this.setRangeButton.Enabled = false;
		}

		private void closeButton_Click(object sender, EventArgs e)
		{
			Close();
		}

		private void contentDataGridView_ColumnDividerDoubleClick(object sender, DataGridViewColumnDividerDoubleClickEventArgs e)
		{
			e.Handled = true;
			this.contentDataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
		}

		private void patternHitsDataGridView_ColumnDividerDoubleClick(object sender, DataGridViewColumnDividerDoubleClickEventArgs e)
		{
			e.Handled = true;
			this.patternHitsDataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
		}

		private void setRangeButton_Click(object sender, EventArgs e)
		{
			this.logWindow.PatternStatisticSelectRange(patternArgs);
			this.recalcButton.Enabled = true;
			this.rangeLabel.Text = "Start: " + patternArgs.startLine + "\r\nEnd: " + patternArgs.endLine;
		}
	}
}